import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class PCAlgo {

	private Map<String, Boolean> tasksMap = new HashMap<String, Boolean>(10);

	public static void main(String[] args) {

		PCAlgo pcAlgo = new PCAlgo();

		Thread producerThread = new Thread(pcAlgo.new ProducerThread());
		Thread consumerThread = new Thread(pcAlgo.new ConsumerThread());

		// start a consumer thread with a delay of 1000 ms between operating on
		// each added task from the map. each task operation takes 100 ms (10
		// tasks in 1000ms)
		consumerThread.start();

		// start a producer thread with a delay of 5000 ms between adding each
		// 10 tasks to map
		producerThread.start();

	}

	class ProducerThread implements Runnable {

		private int LIMIT = 100;

		@Override
		public void run() {
			int i = 0;
			while (tasksMap.size() <= LIMIT) {
				i++;
				System.out.println(" Added task -- " + "task # " + i);
				tasksMap.put("task # " + i, false);// add new task with false
													// completion status

				if (tasksMap.size() == 100) {
					synchronized (tasksMap) {
						try {
							tasksMap.wait();
						} catch (InterruptedException e) {
							// TODO handle interrupted exception
							e.printStackTrace();
						}
					}
				}
			}

		}

	}

	class ConsumerThread implements Runnable {

		@Override
		public void run() {


			synchronized (tasksMap) {
				while (!tasksMap.isEmpty()) {

					Set<String> keys = tasksMap.keySet();
					int cnt = 0;
					for (Iterator<String> iterator = keys.iterator(); iterator
							.hasNext();) {
						String key = iterator.next();
						Boolean completionStatus = tasksMap.get(key);

						if (!completionStatus) {

							cnt++;

							tasksMap.put(key, true);
							System.out.println(" processed task -- " + key);

							if (cnt > 100)
								tasksMap.notify();
						}
					}
				}
			}
		}

	}

}
